package top.fucun.bsm.core.datasource.config;

import top.fucun.bsm.core.aop.DynamicDataSourceAspect;
import top.fucun.bsm.core.datasource.DynamicDataSource;
import top.fucun.bsm.core.datasource.DynamicDataSourceContextHolder;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;

import javax.sql.DataSource;
import java.util.List;
import java.util.Map;

/**
 * @Author: lifucun
 * @Date: 2020/12/21 17:05
 */
@Slf4j
public abstract class DynamicDataSourceConfigBase {

    public final static String DYNAMIC_DATA_SOURCE_NAME = "dynamicDataSource";

    @Primary
    @Bean(DYNAMIC_DATA_SOURCE_NAME)
    public DataSource dynamicDataSource(@Autowired @Qualifier("dataSource")  DataSource dataSource) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        addDefaultDatasource(dataSource);
        dynamicDataSource.setTargetDataSources(getTargetDataSource());
        dynamicDataSource.setDefaultTargetDataSource(dataSource);
        return dynamicDataSource;
    }

    /**
    * 获取所有的 数据源
    * @author: lifucun
    * @date: 2020-12-22 09:15:19
    * @param
    * @throws:
    * @return {@link Map< Object,Object>}
    */
    public abstract Map<Object,Object> getTargetDataSource();

    /**
    * 添加springboot自动配置的数据源
    * @author: lifucun
    * @date: 2020-12-22 12:13:51
    * @param dataSource
    * @throws:
    * @return {@link }
    */
    public abstract void addDefaultDatasource(DataSource dataSource);


    @ConditionalOnProperty("dynamic.datasource.enable")
    @AutoConfigureAfter(DataSourceAutoConfiguration.class)
    @Import({DataSourceConfig.class, DynamicDataSourceAspect.class})
    @EnableConfigurationProperties(DynamicDataSourceProperties.class)
    public static class DynamicDataSourceConfig extends DynamicDataSourceConfigBase {

        @Autowired
        DynamicDataSourceProperties dynamicDataSourceProperties;

        @Override
        public Map<Object, Object> getTargetDataSource() {
            // 加载其它数据源
            List<DataSourceProperties> list = dynamicDataSourceProperties.getList();
            if (null == list || list.isEmpty()) {
                throw new RuntimeException("开启动态数据源配置后,请至少配置额外的一个数据源");
            }
            list.forEach((dataSource) -> {
                // 全部使用HikariDataSource和mysql jdbc
                String name = dataSource.getName();
                String username = dataSource.getUsername();
                String password = dataSource.getPassword();
                String url = dataSource.getUrl();
                String driverClassName = dataSource.getDriverClassName();
                HikariDataSource hikariDataSource = BeanUtils.instantiateClass(HikariDataSource.class);
                hikariDataSource.setUsername(username);
                hikariDataSource.setDriverClassName(driverClassName);
                hikariDataSource.setPassword(password);
                hikariDataSource.setJdbcUrl(url);
                DynamicDataSourceContextHolder.dynamicDatasource.put(name,hikariDataSource);
            });
            log.info("动态数据源加载完成：{}", DynamicDataSourceContextHolder.dynamicDatasource.keySet());
            return DynamicDataSourceContextHolder.dynamicDatasource;
        }

        @Override
        public void addDefaultDatasource(DataSource dataSource) {
            DynamicDataSourceContextHolder.dynamicDatasource.put(DataSourceConfig.DEFAULT_DATA_SOURCE_NAME, dataSource);
        }


    }

}
